Policy Engine
The policy engine is a spend-limit system for autonomous agents. When enabled, it evaluates the USD value of every write operation before execution and rejects anything that exceeds configured limits. It's designed for trading bots and other autonomous systems that need guardrails without human confirmation on every trade.
Enable it with POLICY_ENABLED=true.
Why It Exists
Autonomous agents with CONFIRM_WRITES=false can execute financial transactions without any human approval. That's the point. But unconstrained autonomous execution is dangerous. A bug in the agent's logic, a bad market signal, or a hallucinated token address could drain a wallet in seconds.
The policy engine adds a second layer of protection. Even if the agent's decision-making goes wrong, the policy engine caps the damage. A single bad trade can't exceed POLICY_MAX_SINGLE_TX_USD. A bad day can't exceed POLICY_MAX_DAILY_USD.
Configuration
POLICY_ENABLED=true
POLICY_MAX_SINGLE_TX_USD=100
POLICY_MAX_DAILY_USD=1000
Or when creating a runtime programmatically:
import { createRuntime } from "web3agent/runtime";
const runtime = await createRuntime({
env: {
CHAIN_ID: "8453",
PRIVATE_KEY: "0x...",
CONFIRM_WRITES: "false",
POLICY_ENABLED: "true",
POLICY_MAX_SINGLE_TX_USD: "100",
POLICY_MAX_DAILY_USD: "1000",
}
});
Both limits are optional. You can set just one:
# Only cap individual transactions, no daily limit
POLICY_ENABLED=true
POLICY_MAX_SINGLE_TX_USD=500
# Only cap daily spend, no per-transaction limit
POLICY_ENABLED=true
POLICY_MAX_DAILY_USD=2000
How It Works
Before any financial write operation executes, the policy engine:
- Estimates the USD value of the operation using current token prices.
- Checks the per-transaction limit. If
POLICY_MAX_SINGLE_TX_USDis set and the estimated value exceeds it, the operation is rejected immediately. - Checks the daily limit. If
POLICY_MAX_DAILY_USDis set andtoday's cumulative spend + this operationwould exceed it, the operation is rejected. - Records the spend if the operation is allowed and executes successfully.
Spend Tracking
The policy engine tracks cumulative spend per runtime instance, per calendar day (UTC). The tracker resets at midnight UTC.
Each successful write operation adds its USD value to the daily total. The tracker is in-memory, scoped to the runtime instance. If the process restarts, the daily total resets.
Because spend tracking is in-memory, a process restart clears the daily total. For production autonomous agents, consider this when sizing your POLICY_MAX_DAILY_USD limit. A restart mid-day means the agent could theoretically spend up to the daily limit twice.
Rejection Responses
When the policy engine rejects an operation, the tool returns a structured error:
{
"ok": false,
"error": {
"code": "POLICY_SINGLE_TX_EXCEEDED",
"message": "Transaction value $450.00 exceeds single-transaction limit of $100.00"
}
}
{
"ok": false,
"error": {
"code": "POLICY_DAILY_LIMIT_EXCEEDED",
"message": "Daily spend $950.00 + this transaction $150.00 would exceed daily limit of $1000.00"
}
}
The AI agent receives these errors and can surface them to the user or log them for review.
Example: Trading Agent Configuration
A typical autonomous trading agent configuration with conservative limits:
import { createRuntime } from "web3agent/runtime";
const agentRuntime = await createRuntime({
env: {
CHAIN_ID: "8453",
PRIVATE_KEY: decrypt(agent.walletPrivateKey, encryptionKey),
// Autonomous — no human confirmation step
CONFIRM_WRITES: "false",
// Policy guardrails
POLICY_ENABLED: "true",
POLICY_MAX_SINGLE_TX_USD: String(agent.maxSingleTxUsd), // e.g. "500"
POLICY_MAX_DAILY_USD: String(agent.maxDailyUsd), // e.g. "5000"
}
});
With these settings, the agent can trade freely within its limits. A single swap can't exceed $500. Total daily DeFi activity can't exceed $5,000. Anything beyond those thresholds is rejected before it reaches the blockchain.
Policy vs. Confirmation Queue
These two systems serve different purposes and can run together or independently.
| Confirmation Queue | Policy Engine | |
|---|---|---|
| Purpose | Human approval checkpoint | Automated spend limit enforcement |
| Who decides | A human (or automated approver) | The policy engine, automatically |
| When it runs | Before queuing the operation | Before executing the operation |
| Blocks on | Waiting for transaction_confirm | USD value exceeding limits |
| Best for | Interactive use with a human in the loop | Autonomous agents needing guardrails |
| Env variable | CONFIRM_WRITES | POLICY_ENABLED |
For fully autonomous agents, the typical setup is CONFIRM_WRITES=false with POLICY_ENABLED=true. For interactive use, CONFIRM_WRITES=true with policy disabled (or as an additional layer).
Checking Policy Status
The policy_get tool returns the current policy configuration and today's spend totals:
const result = await runtime.invokeTool("policy_get");
console.log(result.data);
// {
// enabled: true,
// maxSingleTxUsd: 100,
// maxDailyUsd: 1000,
// todaySpendUsd: 347.50,
// remainingDailyUsd: 652.50,
// resetAt: "2026-05-01T00:00:00.000Z"
// }
This is useful for dashboards, health checks, and agent reasoning. An agent can check its remaining daily budget before deciding whether to place a trade.
Configuration Reference
| Variable | Default | Description |
|---|---|---|
POLICY_ENABLED | false | Enable the policy engine |
POLICY_MAX_SINGLE_TX_USD | (none) | Maximum USD value for a single write operation |
POLICY_MAX_DAILY_USD | (none) | Maximum cumulative USD spend per calendar day (UTC) |
All three are optional. POLICY_ENABLED=true with no limits set is valid but has no effect. Set at least one limit for the policy engine to do anything useful.